package concurrency;//: concurrency/PipedIO.java
// Using pipes for inter-task I/O

import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import static net.mindview.util.Print.print;
import static net.mindview.util.Print.printnb;

//class CharQueue extends LinkedBlockingQueue<Character> {
//}
//
//class Sender implements Runnable {
//  private Random rand = new Random(47);
//  private CharQueue queue;
//
//  Sender(CharQueue queue) {
//    this.queue = queue;
//  }
//
//  public void run() {
//    try {
//      while (!Thread.interrupted())
//        for (char c = 'A'; c <= 'z'; c++) {
//          queue.add(c);
//          TimeUnit.MILLISECONDS.sleep(rand.nextInt(500));
//        }
//    } catch (InterruptedException e) {
//      print(e + " Sender sleep interrupted");
//    }
//  }
//}
//
//class Receiver implements Runnable {
//  private CharQueue queue;
//
//  Receiver(CharQueue queue) {
//    this.queue = queue;
//  }
//
//  public void run() {
//    try {
//      while (!Thread.interrupted()) {
//        Character c = queue.take();
//        // Blocks until characters are there:
//        printnb("Read: " + c + ", ");
//      }
//    } catch (InterruptedException e) {
//      print(e + " Receiver read interrupted");
//    }
//  }
//}

class Sender implements Runnable {
  private Random rand = new Random(47);
  private PipedWriter out = new PipedWriter();

  public PipedWriter getPipedWriter() {
    return out;
  }

  public void run() {
    try {
      while (true)
        for (char c = 'A'; c <= 'z'; c++) {
          out.write(c);
          TimeUnit.MILLISECONDS.sleep(rand.nextInt(500));
        }
    } catch (IOException e) {
      print(e + " Sender write exception");
    } catch (InterruptedException e) {
      print(e + " Sender sleep interrupted");
    }
  }
}

class Receiver implements Runnable {
  private PipedReader in;

  public Receiver(Sender sender) throws IOException {
    in = new PipedReader(sender.getPipedWriter());
  }

  public void run() {
    try {
      while (true) {
        // Blocks until characters are there:
        printnb("Read: " + (char) in.read() + ", ");
      }
    } catch (IOException e) {
      print(e + " Receiver read exception");
    }
  }
}

public class PipedIO {

//  public static void main(String[] args) throws Exception {
//    CharQueue queue = new CharQueue();
//    Sender sender = new Sender(queue);
//    Receiver receiver = new Receiver(queue);
//    ExecutorService exec = Executors.newCachedThreadPool();
//    exec.execute(sender);
//    exec.execute(receiver);
//    TimeUnit.SECONDS.sleep(4);
//    exec.shutdownNow();
//  }


  public static void main(String[] args) throws Exception {
    Sender sender = new Sender();
    Receiver receiver = new Receiver(sender);
    ExecutorService exec = Executors.newCachedThreadPool();
    exec.execute(sender);
    exec.execute(receiver);
    TimeUnit.SECONDS.sleep(4);
    exec.shutdownNow();
  }

} /* Output: (65% match)
Read: A, Read: B, Read: C, Read: D, Read: E, Read: F, Read: G, Read: H, Read: I, Read: J, Read: K, Read: L, Read: M, java.lang.InterruptedException: sleep interrupted Sender sleep interrupted
java.io.InterruptedIOException Receiver read exception
*///:~
